#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
EMQX指令发送工具
用于从PC向MaixCAM设备发送各种MQTT指令
"""

import time
import json
import sys
from datetime import datetime

try:
    import paho.mqtt.client as mqtt
except ImportError:
    print("❌ 缺少 paho-mqtt 模块")
    print("请运行: pip install paho-mqtt[websockets]")
    sys.exit(1)

# MQTT配置
BROKER = "82.157.22.162"
PORT = 8083
PATH = "/mqtt"
CLIENT_ID = "admin_commander"  # 管理员客户端ID
DEVICE_CMD_TOPIC = "maixcam/cmd"      # 发送指令的主题
DEVICE_DATA_TOPIC = "maixcam/data"    # 接收设备响应的主题

class EMQXCommander:
    def __init__(self):
        self.client = None
        self.connected = False
        self.responses = []
        
    def on_connect(self, client, userdata, flags, rc):
        if rc == 0:
            print(f"✅ 管理客户端连接成功!")
            self.connected = True
            # 订阅设备响应主题
            client.subscribe(DEVICE_DATA_TOPIC)
            print(f"📡 已订阅设备响应主题: {DEVICE_DATA_TOPIC}")
        else:
            print(f"❌ 连接失败! 错误代码: {rc}")
            self.connected = False
    
    def on_message(self, client, userdata, msg):
        try:
            payload = msg.payload.decode('utf-8')
            timestamp = datetime.now().strftime("%H:%M:%S")
            print(f"\n📥 [{timestamp}] 收到设备响应:")
            print(f"   主题: {msg.topic}")
            print(f"   内容: {payload}")
            
            # 尝试解析JSON
            try:
                data = json.loads(payload)
                if isinstance(data, dict):
                    print("   解析后的数据:")
                    for key, value in data.items():
                        print(f"     {key}: {value}")
            except:
                pass
                
            self.responses.append({
                'timestamp': timestamp,
                'topic': msg.topic,
                'payload': payload
            })
            
        except Exception as e:
            print(f"❌ 处理响应消息失败: {e}")
    
    def on_disconnect(self, client, userdata, rc):
        self.connected = False
        if rc != 0:
            print(f"⚠️ 意外断开连接! 代码: {rc}")
    
    def connect(self):
        try:
            print("🔗 正在连接EMQX服务器...")
            self.client = mqtt.Client(
                client_id=CLIENT_ID,
                transport="websockets"
            )
            
            self.client.on_connect = self.on_connect
            self.client.on_message = self.on_message
            self.client.on_disconnect = self.on_disconnect
            
            self.client.ws_set_options(path=PATH)
            self.client.connect(BROKER, PORT, 60)
            self.client.loop_start()
            
            # 等待连接
            for i in range(10):
                if self.connected:
                    return True
                time.sleep(1)
                print(f"   等待连接... {i+1}/10")
            
            return False
        except Exception as e:
            print(f"❌ 连接失败: {e}")
            return False
    
    def disconnect(self):
        if self.client:
            self.client.loop_stop()
            self.client.disconnect()
            print("🔌 连接已断开")
    
    def send_command(self, command, wait_response=True):
        if not self.connected:
            print("❌ 未连接到服务器")
            return False
        
        try:
            # 清空之前的响应
            if wait_response:
                self.responses.clear()
            
            # 发送指令
            result = self.client.publish(DEVICE_CMD_TOPIC, command)
            timestamp = datetime.now().strftime("%H:%M:%S")
            
            if result.rc == 0:
                print(f"\n📤 [{timestamp}] 指令发送成功:")
                print(f"   主题: {DEVICE_CMD_TOPIC}")
                print(f"   内容: {command}")
                
                # 等待响应
                if wait_response:
                    print("⏳ 等待设备响应...")
                    time.sleep(3)  # 等待3秒接收响应
                    
                return True
            else:
                print(f"❌ 指令发送失败: {result.rc}")
                return False
                
        except Exception as e:
            print(f"❌ 发送指令时出错: {e}")
            return False

def show_menu():
    print("\n" + "="*50)
    print("🎛️  EMQX 设备指令控制台")
    print("="*50)
    print("1. 发送 ping 指令")
    print("2. 查询设备状态")
    print("3. 控制LED开关")
    print("4. 控制摄像头云台")
    print("5. 拍照功能")
    print("6. 重启设备")
    print("7. 获取传感器数据")
    print("8. 发送自定义JSON指令")
    print("9. 发送自定义文本指令")
    print("10. 查看历史响应")
    print("0. 退出")
    print("-"*50)

def get_predefined_commands():
    """预定义的指令模板"""
    return {
        "ping": "ping",
        "status": "status",
        "led_flash_1s": {
            "type": "led",
            "state": "flash",
            "duration": 1.0
        },
        "led_flash_3s": {
            "type": "led",
            "state": "flash", 
            "duration": 3.0
        },
        "led_off": {
            "type": "led", 
            "state": "off"
        },
        "restart": {
            "type": "system",
            "action": "restart"
        },
        "get_sensors": {
            "type": "sensor",
            "action": "read_all"
        }
    }

def main():
    print("🚀 EMQX设备指令控制工具启动")
    print(f"目标服务器: {BROKER}:{PORT}")
    
    commander = EMQXCommander()
    
    # 连接到服务器
    if not commander.connect():
        print("❌ 无法连接到EMQX服务器")
        return
    
    commands = get_predefined_commands()
    
    try:
        while True:
            show_menu()
            choice = input("请选择操作 (0-9): ").strip()
            
            if choice == '0':
                break
            elif choice == '1':
                # 发送ping
                commander.send_command(commands["ping"])
                
            elif choice == '2':
                # 查询状态
                commander.send_command(commands["status"])
                
            elif choice == '3':
                # LED控制
                print("\nLED控制选项:")
                print("1. 闪烁1秒")
                print("2. 闪烁3秒")
                print("3. 自定义闪烁时间")
                print("4. 关闭LED")
                led_choice = input("请选择 (1-4): ").strip()
                
                if led_choice == '1':
                    commander.send_command(json.dumps(commands["led_flash_1s"], ensure_ascii=False))
                elif led_choice == '2':
                    commander.send_command(json.dumps(commands["led_flash_3s"], ensure_ascii=False))
                elif led_choice == '3':
                    duration = input("请输入闪烁时间(秒, 默认1): ").strip()
                    try:
                        duration = float(duration) if duration else 1.0
                        cmd = {
                            "type": "led",
                            "state": "flash",
                            "duration": duration
                        }
                        commander.send_command(json.dumps(cmd, ensure_ascii=False))
                    except ValueError:
                        print("❌ 时间值无效")
                elif led_choice == '4':
                    commander.send_command(json.dumps(commands["led_off"], ensure_ascii=False))
                
            elif choice == '4':
                # 摄像头云台控制
                print("\n摄像头云台控制 (PWM电机控制):")
                print("1. 向上移动 (A19=高, A18=低)")
                print("2. 向下移动 (A19=低, A18=高)")
                print("3. 向左移动 (A16=高, A17=低)")
                print("4. 向右移动 (A16=低, A17=高)")
                print("5. 自定义移动")
                camera_choice = input("请选择 (1-5): ").strip()
                
                if camera_choice in ['1', '2', '3', '4']:
                    directions = {'1': 'up', '2': 'down', '3': 'left', '4': 'right'}
                    direction = directions[camera_choice]
                    
                    time_duration = input(f"请输入移动时间(秒, 默认0.5): ").strip()
                    try:
                        time_duration = float(time_duration) if time_duration else 0.5
                        cmd = {
                            "type": "camera",
                            "direction": direction,
                            "time": time_duration
                        }
                        commander.send_command(json.dumps(cmd, ensure_ascii=False))
                    except ValueError:
                        print("❌ 时间值无效")
                        
                elif camera_choice == '5':
                    direction = input("请输入方向 (up/down/left/right): ").strip()
                    if direction in ['up', 'down', 'left', 'right']:
                        time_duration = input("请输入时间 (默认0.5): ").strip()
                        try:
                            time_duration = float(time_duration) if time_duration else 0.5
                            cmd = {
                                "type": "camera", 
                                "direction": direction,
                                "time": time_duration
                            }
                            commander.send_command(json.dumps(cmd, ensure_ascii=False))
                        except ValueError:
                            print("❌ 参数值无效")
                    else:
                        print("❌ 无效方向")
                        
            elif choice == '5':
                # 拍照功能
                print("\n拍照功能:")
                print("1. 拍照并通过MQTT发送")
                print("2. 只拍照保存，不发送")
                print("3. 自定义文件名拍照")
                photo_choice = input("请选择 (1-3): ").strip()
                
                if photo_choice == '1':
                    # 默认拍照并发送
                    cmd = {
                        "type": "photo",
                        "send": True
                    }
                    commander.send_command(json.dumps(cmd, ensure_ascii=False))
                    
                elif photo_choice == '2':
                    # 只拍照不发送
                    cmd = {
                        "type": "photo",
                        "send": False
                    }
                    commander.send_command(json.dumps(cmd, ensure_ascii=False))
                    
                elif photo_choice == '3':
                    # 自定义文件名
                    filename = input("请输入文件名 (不包含扩展名): ").strip()
                    send_mqtt = input("是否通过MQTT发送? (y/N): ").strip().lower() == 'y'
                    
                    cmd = {
                        "type": "photo",
                        "filename": filename if filename else None,
                        "send": send_mqtt
                    }
                    commander.send_command(json.dumps(cmd, ensure_ascii=False))
                    
            elif choice == '6':
                # 重启设备
                confirm = input("⚠️  确定要重启设备吗? (y/N): ").strip().lower()
                if confirm == 'y':
                    commander.send_command(json.dumps(commands["restart"], ensure_ascii=False))
                else:
                    print("操作已取消")
                    
            elif choice == '7':
                # 获取传感器数据
                commander.send_command(json.dumps(commands["get_sensors"], ensure_ascii=False))
                
            elif choice == '8':
                # 自定义JSON指令
                print("\n请输入JSON格式的指令:")
                print("示例: {\"type\": \"custom\", \"action\": \"test\"}")
                custom_json = input("JSON指令: ").strip()
                
                try:
                    # 验证JSON格式
                    json.loads(custom_json)
                    commander.send_command(custom_json)
                except json.JSONDecodeError:
                    print("❌ JSON格式错误")
                    
            elif choice == '8':
                # 自定义文本指令
                custom_text = input("请输入文本指令: ").strip()
                if custom_text:
                    commander.send_command(custom_text)
                    
            elif choice == '9':
                # 查看历史响应
                if commander.responses:
                    print("\n📜 历史响应记录:")
                    for i, resp in enumerate(commander.responses[-10:], 1):  # 显示最近10条
                        print(f"{i}. [{resp['timestamp']}] {resp['topic']}")
                        print(f"   {resp['payload']}")
                else:
                    print("📭 暂无响应记录")
                    
            elif choice == '9':
                # 清空历史
                commander.responses.clear()
                print("✅ 响应历史已清空")
                
            else:
                print("❌ 无效选择")
                
            input("\n按回车键继续...")
            
    except KeyboardInterrupt:
        print("\n⚠️ 接收到退出信号")
    finally:
        commander.disconnect()
        print("👋 程序结束")

if __name__ == "__main__":
    main()